home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 2000 October / Software of the Month - Ultimate Collection Shareware 277.iso / pc / PROGRAMS / UTILITY / WINLINUX / DATA1.CAB / usr_-_Usr_Files / INCLUDE / REGEXP.H < prev    next >
C/C++ Source or Header  |  1999-09-17  |  5KB  |  225 lines

  1. /*
  2.  * regexp.h -- old-style regexp compile and step (emulated with POSIX regex)
  3.  * Copyright (C) 1993 Rick Sladkey <jrs@world.std.com>
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU Library Public License as published by
  7.  * the Free Software Foundation; either version 2, or (at your option)
  8.  * any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU Library Public License for more details.
  14.  */
  15.  
  16. /*
  17.  * Think really hard before you intentionally include this file.
  18.  * You should really be using the POSIX regex interface instead.
  19.  * This emulation file is intended solely for compiling old code.
  20.  *
  21.  * A program that uses this file must define six macros: INIT,
  22.  * GETC, PEEKC, UNGETC, RETURN, and ERROR.  This interface is
  23.  * so arcane that VMS hackers point at it in ridicule.
  24.  */
  25.  
  26. #ifndef _REGEXP_H
  27. #define _REGEXP_H
  28.  
  29. #include <sys/types.h>            /* regex.h needs size_t */
  30. #include <regex.h>            /* POSIX.2 regexp routines */
  31. #include <stdlib.h>            /* for malloc, realloc and free */
  32.  
  33. /*
  34.  * These three advertised external variables record state information
  35.  * for compile and step.  They are so gross, I'm choking as I write this.
  36.  */
  37. char *loc1;                /* the beginning of a match */
  38. char *loc2;                /* the end of a match */
  39. int circf;                /* current pattern begins with '^' */
  40.  
  41. /*
  42.  * These are the other variables mentioned in the regexp.h manpage.
  43.  * Since we don't emulate them (whatever they do), we want errors if
  44.  * they are referenced.  Therefore they are commented out here.
  45.  */
  46. #if 0
  47. char *locs;
  48. int sed;
  49. int nbra;
  50. #endif
  51.  
  52. /*
  53.  * We need to stuff a regex_t into an arbitrary buffer so align it.
  54.  * GCC make this easy.  For the others we have to guess.
  55.  */
  56. #ifdef __GNUC__
  57. #define __REGEX_T_ALIGN (__alignof__(regex_t))
  58. #else /* !__GNUC__ */
  59. #define __REGEX_T_ALIGN 8
  60. #endif /* !__GNUC__ */
  61.  
  62. #define __regex_t_align(p)                        \
  63.     ((regex_t *) ((((unsigned long) p) + __REGEX_T_ALIGN - 1)    \
  64.         / __REGEX_T_ALIGN * __REGEX_T_ALIGN))
  65.  
  66. /*
  67.  * We just slurp the whole pattern into a string and then compile
  68.  * it `normally'.  With this implementation we never use the PEEKC
  69.  * macro.  Please feel free to die laughing when we translate
  70.  * error symbols into hard-coded numbers.
  71.  */
  72. char *
  73. compile(char *instring, char *expbuf, char *endbuf, int eof)
  74. {
  75.     int __c;
  76.     int __len;
  77.     char *__buf;
  78.     int __buflen;
  79.     int __error;
  80.     regex_t *__preg;
  81.     INIT;
  82.  
  83.     __buflen = 128;
  84.     __buf = malloc(__buflen);
  85.     if (!__buf) {
  86.         ERROR(50);
  87.         return 0;
  88.     }
  89.     __len = 0;
  90.     circf = 0;
  91.     for (;;) {
  92.         __c = GETC();
  93.         if (__c == eof)
  94.             break;
  95.         if (__c == '\0' || __c == '\n') {
  96.             UNGETC(__c);
  97.             break;
  98.         }
  99.         if (__len + 2 > __buflen) {
  100.             __buflen *= 2;
  101.             __buf = realloc(__buf, __buflen);
  102.             if (!__buf) {
  103.                 ERROR(50);
  104.                 return 0;
  105.             }
  106.         }
  107.         if (__len == 0 && !circf && __c == '^')
  108.             circf = 1;
  109.         else
  110.             __buf[__len++] = __c;
  111.     }
  112.     if (__len == 0 && !circf) {
  113.         free(__buf);
  114.         ERROR(41);
  115.         return 0;
  116.     }
  117.     __buf[__len] = '\0';
  118.     if (endbuf <= expbuf + sizeof(regex_t)) {
  119.         free(__buf);
  120.         ERROR(50);
  121.         return 0;
  122.     }
  123.     __preg = __regex_t_align(expbuf);
  124.     __preg->buffer = (char *) (__preg + 1);
  125.     __preg->allocated = endbuf - (char *) __preg->buffer;
  126.     __error = regcomp(__preg, __buf, REG_NEWLINE);
  127.     free(__buf);
  128.     switch (__error) {
  129.     case 0:
  130.         break;
  131.     case REG_BADRPT:
  132.         __error = 36; /* poor fit */
  133.         break;
  134.     case REG_BADBR:
  135.         __error = 16;
  136.         break;
  137.     case REG_EBRACE:
  138.         __error = 44; /* poor fit */
  139.         break;
  140.     case REG_EBRACK:
  141.         __error = 49;
  142.         break;
  143.     case REG_ERANGE:
  144.         __error = 36; /* poor fit */
  145.         break;
  146.     case REG_ECTYPE:
  147.         __error = 36; /* poor fit */
  148.         break;
  149.     case REG_EPAREN:
  150.         __error = 42;
  151.         break;
  152.     case REG_ESUBREG:
  153.         __error = 36; /* poor fit */
  154.         break;
  155.     case REG_EEND:
  156.         __error = 36; /* poor fit */
  157.         break;
  158.     case REG_EESCAPE:
  159.         __error = 36;
  160.         break;
  161.     case REG_BADPAT:
  162.         __error = 36; /* poor fit */
  163.         break;
  164.     case REG_ESIZE:
  165.         __error = 50;
  166.         break;
  167.     case REG_ESPACE:
  168.         __error = 50;
  169.         break;
  170.     default:
  171.         __error = 36; /* as good as any */
  172.         break;
  173.     }
  174.     if (__error) {
  175.         ERROR(__error);
  176.         return 0;
  177.     }
  178. #ifdef _RX_H
  179.     RETURN((__preg->buffer + __preg->rx.allocated - __preg->rx.reserved));
  180. #else
  181.     RETURN((__preg->buffer + __preg->used));
  182. #endif
  183. }
  184.  
  185. /*
  186.  * Note how we carefully emulate the gross `circf' hack.  Otherwise,
  187.  * this just looks like an ordinary matching call that records the
  188.  * starting and ending match positions.
  189.  */
  190. int
  191. step(char *string, char *expbuf)
  192. {
  193.     int __result;
  194.     regmatch_t __pmatch[1];
  195.  
  196.     __result = regexec(__regex_t_align(expbuf), string, 1, __pmatch, 0);
  197.     if (circf && __pmatch[0].rm_so != 0)
  198.         __result = REG_NOMATCH;
  199.     if (__result == 0) {
  200.         loc1 = string + __pmatch[0].rm_so;
  201.         loc2 = string + __pmatch[0].rm_eo;
  202.     }
  203.     return __result == 0;
  204. }
  205.  
  206. /*
  207.  * For advance we are only supposed to match at the beginning of the
  208.  * string.  You have to read the man page really carefully to find this
  209.  * one.  We'll match them kludge-for-kludge.
  210.  */
  211. int
  212. advance(char *string, char *expbuf)
  213. {
  214.     int __old_circf;
  215.     int __result;
  216.  
  217.     __old_circf = circf;
  218.     circf = 1;
  219.     __result = step(string, expbuf);
  220.     circf = __old_circf;
  221.     return __result;
  222. }
  223.  
  224. #endif /* _REGEXP_H */
  225.